import { defineNuxtPlugin } from "nuxt/app";
import { useGlobalStore } from "~~/store/global";
import { useUserStore } from "~~/store/modules/user";
import { bridge } from "~~/utils/bridge";
import { useEventBus } from "@vueuse/core";
import { getUserInfo } from "../api/user";
import { DANA_PACKAGE_ID } from "~~/config";
import { useEnvConfigInfo } from "~/utils/index";
import { usePageVisibility } from "@vant/use";

/**
 * @description: 通过桥接获取 App 的回调信息
 * 1. 如果 10 次总共 3 秒获取不到 token 就相当于是获取失败了。在重复获取也没有意义了
 * 2. 链接传入的token ,优先级高于,从服务端获取的 token ，高于，从 app 获取的 token;
 * 3. 切换页面后，在次获取 token 一次；
 * 4. 跳转app登录页面后，返回 h5 在次获取 token 一次；
 * 5. 获取到 token ，获取用户信息保存到 store 中
 */
export default defineNuxtPlugin((nuxtApp) => {
  const globalStore = useGlobalStore();
  const route = useRoute();
  const router = useRouter();
  const useLanguage = useEventBus("language-change");
  // const unmountedToken = useEventBus("token:unmounted");
  // const mountedToken = useEventBus("token:mounted");
  const userState = useUserStore();
  const pageVisibility = usePageVisibility();
  const { WEB_NODE_ENV = "prod", version } = useRuntimeConfig().public;

  console.log("当前网址：", location.href, "--解析：", route.query);
  console.log("当前 h5 版本：", version);

  let token = bridge.getAppToken();
  let language = bridge.getAppLanguage(); // 获取语言
  let packageId = bridge.getAppPackageId(); // 获取packageId
  let route_token = "";
  let route_language = "";
  let route_packageId = "";
  if (route.query && route.query.language) {
    route_language = route.query.language as string;
    console.log("URL链接 -- 传入language:", route_language);
  }
  if (route.query && route.query.token) {
    route_token = route.query.token as string;
    console.log("URL链接 -- 传入token:", route_token);
  }
  if (route.query && route.query.packageId) {
    route_packageId = route.query.packageId as string;
    console.log("URL链接 -- 传入版本:", route_packageId);
  }

  // 主动调用安卓或iOS注册的事件，来获取数据或处理一些特殊问题
  const initApp = () => {
    console.log("initApp执行");

    try {
      if (!token) {
        const token_app = bridge.getAppToken();
        if (token_app) {
          token = token_app;
          console.log("app 传入token:", token_app);
        }
      }
      if (!language) {
        const language_app = bridge.getAppLanguage(); // 获取语言
        if (language_app) {
          language = language_app;
          console.log("app 传入language:", language_app);
        }
      }
      if (!packageId) {
        const packageId_app = bridge.getAppPackageId(); // 获取packageId
        if (packageId_app) {
          packageId = packageId_app;
          console.log("app 传入packageId:", packageId_app);
        }
      }

      /************************* 调试-配置 **********************/
      if (route_language) language = route_language;
      if (route_token) token = route_token;
      if (route_packageId) packageId = route_packageId;
      // 开发环境自己使用
      else if (process.env.NODE_ENV == "development") {
        token = useEnvConfigInfo().token;
        console.log("使用默认 token");
      }
      // console.log("store-header:",globalStore.$state);

      /************************* 赋值 **********************/
      if (token && globalStore.$state.token != token) {
        globalStore.$patch((state) => {
          state.token = token;
        });
      }

      if (language && language != globalStore.$state.language) {
        globalStore.$patch((state) => {
          state.language = language ?? "en";
        });
      }

      if (packageId && packageId != globalStore.$state.packageId) {
        globalStore.$patch((state) => {
          state.packageId = packageId ?? "";
        });
      }
      // 这里的方式不行
      // if (packageId && !globalStore.$state.isDhApp) {
      //  globalStore.$patch((state) => {
      //     state.isDhApp = true;
      //   });
      // }
    } catch (error) {
      console.log(error);
    }
  };

  // 未登录通知
  const tokenUnmounted = (() => {
    let isNotice = true;
    return () => {
      if (isNotice) {
        // unmountedToken.emit();
        isNotice = false;
      }
    };
  })();

  /**
   * @description: 保存 APP(主要还是 iOS) 传递给 h5 的信息 useRequestHeaders 里面的值
   */
  const saveAppInfoLocal = () => {
    // console.log("--saveAppInfoLocal:",globalStore.$state);

    localStorage.setItem(
      "appInitH5Prams",
      JSON.stringify({
        token: globalStore.$state.token,
        language: globalStore.$state.language,
        packageId: globalStore.$state.packageId,
        statusBarHeight: `${globalStore.$state.statusBarHeight || 20}`,
        IsIphoneX: globalStore.$state.IsIphoneX ? "1" : "0",
      })
    );
    localStorage.setItem("token", globalStore.$state.token);
    localStorage.setItem("language", globalStore.$state.language);
    localStorage.setItem("packageId", globalStore.$state.packageId);
    localStorage.setItem(
      "statusBarHeight",
      `${globalStore.$state.statusBarHeight || 20}`
    );
    localStorage.setItem("IsIphoneX", globalStore.$state.IsIphoneX ? "1" : "0");
  };

  // 1. 将默认语言保存到 store 中
  // console.log("--globalStore.$state--",globalStore.$state);
  globalStore.$patch({
    language:
      globalStore.$state.language ||
      language ||
      route_language ||
      (nuxtApp.$i18n as any).locale.value ||
      "en",
    packageId:
      packageId ||
      route_packageId ||
      globalStore.$state.packageId ||
      (route.query && route.query.packageId
        ? (route.query.packageId as string)
        : DANA_PACKAGE_ID.value),
  });

  // 1.1 全局 token 处理逻辑
  const tokenLogic = () => {
    /**
     * @description: token 的变化监听
     * 1. 保存 token 到缓存中,由于更新 token 的方式很多,这里统一处理
     * 2. 如果 内存中的 token 释放了,重新从缓存中获取
     */
    watch(
      () => globalStore.$state.token,
      (newValue, oldValue) => {
        if (newValue) {
          // 1. 赋值: 覆盖
          if (newValue != oldValue && process.client) {
            localStorage.setItem("token", newValue);
          }
          // 2. 通知各个页面
          // mountedToken.emit({
          //   token:globalStore.$state.token,
          //   language:globalStore.$state.language,
          //   packageId:globalStore.$state.packageId,
          // });
          // 3. 获取用户信息
          getUserInfo().then((res) => {
            // console.log("--用户信息--", res);
            if (res && res.code === 200 && res.data?.user) {
              userState.$state = res.data.user as any;
            }
          });
        }
      },
      { immediate: true, deep: true }
    );

    /**
     * @description: 解决,app 长时间挂起,token 内存释放,进入还需要重新登录的情况:但是好像没有起作用,暂时先保留
     */
    const pageVisibility = usePageVisibility();
    watch(pageVisibility, (value) => {
      if (value == "visible" && !globalStore.$state.token) {
        const t = localStorage.getItem("token");
        if (t) {
          globalStore.setUserToken(t);
        }
      }
    });
  };
  tokenLogic();

  // 2. 在安装应用程序之前调用，仅在客户端调用。
  nuxtApp.hook("app:beforeMount", initApp);
  // 3. 资源挂载完成:判断是否已经拿到token，如果没有拿到token，就每隔n秒去拿一次
  nuxtApp.hook("app:mounted", () => {
    let num = 0;
    let timer: string | number | NodeJS.Timeout | undefined;
    const cycleCall = () => {
      if (globalStore.$state.token || num > 10) {
        // 1. 清除定时器
        clearInterval(timer);
        // 2. 保存获取到的信息到 localStore
        setTimeout(() => {
          saveAppInfoLocal();
        }, 6000);
      } else {
        initApp();
      }

      // 3. 没有拿到token，提示用户
      if (num > 10 && !globalStore.$state.token) {
        // 3.1
        tokenUnmounted();
        console.log("no token");

        // 3.2 未知原因,跳转页面失去 APP 传递的参数,这里重新赋值,app 传递给 h5 的useRequestHeaders信息
        const statusBarHeight_local =
          localStorage.getItem("statusBarHeight") || 0;
        if (
          statusBarHeight_local &&
          Number(statusBarHeight_local) > 0 &&
          !globalStore.$state.statusBarHeight
        ) {
          console.log("未知原因,跳转页面失去 APP 传递的参数,这里重新赋值");
          const packageId_local = localStorage.getItem("packageId");
          const language_local = localStorage.getItem("language");
          const IsIphoneX_local = localStorage.getItem("IsIphoneX");
          globalStore.$patch((state) => {
            state.language = language_local || "en";
            state.packageId = packageId_local || "";
            state.statusBarHeight = Number(statusBarHeight_local) || 20;
            state.IsIphoneX = Number(IsIphoneX_local) == 1 ? true : false;
          });
        }
      }
      num++;
    };
    // 初始化调用一次
    cycleCall();
    // 每隔300毫秒去拿一次token，如果拿到了就清除定时器
    timer = setInterval(cycleCall, 300);
  });

  // 4. 在没有获取到 token 的情况下。切换页面的时候在最后获取去一次.如果还没有获取到，可以主动弹窗提示去登录
  watch(
    () => router.currentRoute.value,
    () => {
      // 1. 重试机制
      if (!globalStore.$state.token && globalStore.$state.isRetry) {
        globalStore.$state.isRetry = false; // 改变重试状态，进入登录页面以后，返回 h5 在重新获取
        initApp();
      }
      // 2. 未登录
      if (!globalStore.$state.token && !globalStore.$state.isRetry) {
        tokenUnmounted();
      }
    }
  );

  // 4.1 当页面进入视野，未登录情况，再次尝试获取 token
  watch(pageVisibility, (value) => {
    console.log("从后台进入前台: callApp.client.ts", value);
    if (
      !globalStore.$state.token &&
      globalStore.$state.isRetry &&
      value == "visible"
    ) {
      globalStore.$state.isRetry = false; // 改变重试状态，进入登录页面以后，返回 h5 在重新获取
      initApp();
    }
  });

  // 6. 动态切换语言,(全局只能，也只有这一个地方可以切换语言)
  const languageCahnge = (event: any) => {
    // console.log("动态切换语言:", event);
    (nuxtApp as any).$i18n.locale.value = event;
    (nuxtApp.$i18n as any).fallbackLocale.value = event;
    (nuxtApp.$i18n as any).defaultLocale = event; // 这里设置默认值，以便入口页面跳转 A 页面返回入口页面展示默认语言的 bug
  };
  useLanguage.on(languageCahnge);
  watch(
    () => globalStore.$state.language,
    (newVal, oldVal) => {
      try {
        if (newVal) {
          console.log("当前语言：", oldVal, "切换成：", newVal);
          languageCahnge(newVal);
        }
      } catch (error) {
        console.log(error);
      }
    },
    {
      immediate: true,
    }
  );
});
